package com.kuang.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.logging.log4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;

import java.util.HashSet;
import java.util.Set;

@Configuration
public class RedisConfig {

//    @Value("${spring.redis.sentinel.nodes}")
//    private String sentinelNodes;
//
//    @Value("${spring.redis.sentinel.master}")
//    private String masterName;

    /**
     * JedisPool相关配置
     */
    @Component
    @ConfigurationProperties(prefix = "spring.redis.cluster")
    public class ClusterPoolConfigProp {
        String nodes;
        int expireSeconds;
        int commandTimeout;
        int maxAttempts;

        public String getNodes() {
            return nodes;
        }

        public void setNodes(String nodes) {
            this.nodes = nodes;
        }

        public int getExpireSeconds() {
            return expireSeconds;
        }

        public void setExpireSeconds(int expireSeconds) {
            this.expireSeconds = expireSeconds;
        }

        public int getCommandTimeout() {
            return commandTimeout;
        }

        public void setCommandTimeout(int commandTimeout) {
            this.commandTimeout = commandTimeout;
        }

        public int getMaxAttempts() {
            return maxAttempts;
        }

        public void setMaxAttempts(int maxAttempts) {
            this.maxAttempts = maxAttempts;
        }
    }

    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        return template;
    }

    /**
     *
     * @author Fire Monkey
     * @date 2018/3/12 下午6:53
     * @return redis.clients.jedis.JedisPoolConfig
     * 初始化连接池配置对象
     *
     */
    @Bean(value = "jedisPoolConfig")
    public JedisPoolConfig initJedisPoolConfig(){
        JedisPoolConfig config = new JedisPoolConfig();

        //常规配置
        config.setTestOnBorrow(true);
        config.setTestOnReturn(true);
        return config;
    }

    /**
     *
     * @author Fire Monkey
     * @date 下午7:20
     * @return redis.clients.jedis.JedisSentinelPool
     * 生成JedisSentinelPool并且放入Spring容器
     *
     */
//    @Bean
//    public JedisSentinelPool jedisSentinelPool(JedisPoolConfig jedisPoolConfig){
//
//        Set<String> nodeSet = new HashSet<>();
//        //判断字符串是否为空
//        if(sentinelNodes == null || "".equals(sentinelNodes)){
//            throw new RuntimeException("RedisSentinelConfiguration initialize error nodeString is null");
//        }
//        String[] nodeArray = sentinelNodes.split(",");
//        //判断是否为空
//        if(nodeArray == null || nodeArray.length == 0){
//            throw new RuntimeException("RedisSentinelConfiguration initialize error nodeArray is null");
//        }
//        //循环注入至Set中
//        for(String node : nodeArray){
//            nodeSet.add(node);
//        }
//        //创建连接池对象
//        JedisSentinelPool jedisPool = new JedisSentinelPool(masterName ,nodeSet ,jedisPoolConfig);
//        return jedisPool;
//    }

    @Bean
    public JedisCluster jedisCluster(ClusterPoolConfigProp clusterPoolConfigProp){
        //获取redis集群的ip及端口号等相关信息；
        String[] serverArray = clusterPoolConfigProp.getNodes().split(",");
        Set<HostAndPort> nodes = new HashSet<>();

        //遍历add到HostAndPort中；
        for (String ipPort : serverArray) {
            String[] ipPortPair = ipPort.split(":");
            nodes.add(new HostAndPort(ipPortPair[0].trim(), Integer.valueOf(ipPortPair[1].trim())));
        }
        //构建对象并返回；
        return new JedisCluster(nodes, clusterPoolConfigProp.getCommandTimeout());
    }
}